#include <iostream>
#include <fstream>
#include <string>
#include <array>
#include <vector>
#include <iomanip>

using Byte16 = std::array<uint8_t,16>;//16 字节数组

int hexCharToVal(char c) {
    if (c >= '0' && c <= '9') return c - '0';
    if (c >= 'a' && c <= 'f') return 10 + (c - 'a');
    if (c >= 'A' && c <= 'F') return 10 + (c - 'A');
    return -1;
}

void read_file_key(std::vector<Byte16>& keySet,std::string input_file){
    
    std::ifstream fin(input_file);
    if(!fin.is_open()){
        std::cerr<<"can't open file::"<<input_file<<std::endl;
        return;
    }
     std::string line;
     while (std::getline(fin,line))
     {
        if(line.size()!=32) break;
        Byte16 bytes;
        for (int i = 0; i < 16; ++i) {
            int hi = hexCharToVal(line[2*i]);
            int lo = hexCharToVal(line[2*i+1]);
            bytes[i] = (hi << 4) | lo;
        }
        keySet.push_back(bytes);
     }
     fin.close();
}


void crypt_file(const Byte16& key,
                  const std::string& inPath,
                  const std::string& outPath)
{
    std::ifstream fin(inPath, std::ios::binary);
         if (!fin) throw std::runtime_error("无法打开输入文件: " + inPath);

    std::ofstream fout(outPath, std::ios::binary);
         if (!fout) throw std::runtime_error("无法打开输出文件: " + outPath);

    std::array<uint8_t, 16> buffer;
    while (true) {
        // 读最? 16 字节
        fin.read(reinterpret_cast<char*>(buffer.data()), buffer.size());
        std::streamsize n = fin.gcount();
        if (n <= 0) break;

        // 对读到的每个字节? XOR
        for (std::streamsize i = 0; i < n; ++i) {
            buffer[i] ^= key[i];
        }
        // 写回加密后的字节
        fout.write(reinterpret_cast<char*>(buffer.data()), n);

        if (!fin) break;  // EOF 或其他读入失?
    }
    fin.close();
    fout.close();
}

void print_bytes(const Byte16 &b);

int main(int argc, char* argv[]) {
    
    if(argc!=4){
        std::cerr<<"params error\n";
        return 1;
    }

    std::string key_file = argv[1];    
    std::string input_path = argv[2]; //输入文件
    std::string output_path = argv[3];//输出文件
    std::vector<Byte16>keySet;

    read_file_key(keySet,key_file);
    for(int i=0;i<128;i++){
        std::string  enc_file = input_path+"/"+std::to_string(i+1)+".bin"; 
        std::string  out_file = output_path+"/"+std::to_string(i+1)+".bin"; 
        crypt_file(keySet[i],enc_file,out_file);
    }
    return 0;
}



void print_bytes(const Byte16 &b) {
    for (size_t i = 0; i < b.size(); ++i) {
        // 每个 byte 以两? hex 打印，不足补 0
        std::cout
            << std::hex << std::setw(2) << std::setfill('0')
            << static_cast<int>(b[i]);
    }
    std::cout << std::dec << '\n';   // 恢复为十进制输出
}
